package display.client;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;

import track.Classification_enum;
import track.PointTrack;
import track.TrackState;

public class IdentificationData {

    // Map of information on published TrackState instances.
    private static HashMap<Integer, TrackState> m_published = new HashMap<Integer, TrackState>();

    // Map of "to be published" TrackState instances. We model the
    // identification delay by placing the newly-created TrackState 
    // instances in this map, and classifying publishing once the 
    // delay has been performed. At this point, the instances are
    // removed from this map and placed in m_published.
    private static TreeMap<Integer, TrackState> m_pending = new TreeMap<Integer, TrackState>();

    public static String m_padding = new String ("");
    
    public static void disposeTrackStateWithId(Integer id) {
        //System.out.println ("IdentificationData dispose object " + id);
        m_published.remove(id);
    }

    public static void getPointTracks() {
        PointTrack[] tracks = null;
        /*      
        get disposed point tracks  
        for (int i = 0; i < tracks.length; i++) {
            PointTrack track = tracks[i];
            Integer mapKey = new Integer(track.trackId);

            // It's valid for there to be no map entry; this will happen
            // for an object that never came
            // within sensor range.
            TrackState info = (TrackState) m_published.get(mapKey);
            if (info != null) {
                // Remove from the map.
                m_published.remove(mapKey);
            }
        }*/

        //
        // Second take: retrieve new instances on this topic and provide
        // classification.
        // Unlike Sensor, we separate the take calls since
        // Identification is intended to
        // only perform classification once for each object.
        //
        tracks = SensorData.getPointTracksWithoutUpdate();
        for (int i = 0; i < tracks.length; i++) {
            PointTrack track = tracks[i];

            Integer publishedKey = new Integer(track.trackId);
            TrackState info = (TrackState) m_published.get(publishedKey);
            if (info != null) {
                // Already classified.
                continue;
            }

            // Create the new TrackState instance.
            TrackState newInfo = new TrackState();
            newInfo = new TrackState();
            newInfo.trackId = track.trackId;
            newInfo.padding = m_padding;

            synchronized (m_pending) {
                m_pending.put(newInfo.trackId, newInfo);
            }   
        }        
    }
    
    public static void updateObjects() {
        getPointTracks ();
        // If nothing in the map, loop.
        if (m_pending.size() == 0) {
            return;
        }    

        int publishedCount = 0;
        Integer pendingKey;
        synchronized (m_pending) {
            pendingKey = (Integer) m_pending.firstKey();

            TrackState info = (TrackState) m_pending.get(pendingKey);

            long value = System.currentTimeMillis();
            // Generate the classification for this ID.
            switch (((int)value) % 3) {
            case 0:
                info.classification = Classification_enum.TRACK_CLASSIFICATION_UNKNOWN;
                break;
            case 1:
                info.classification = Classification_enum.TRACK_CLASSIFICATION_HOSTILE;
                break;
            case 2:
                info.classification = Classification_enum.TRACK_CLASSIFICATION_FRIENDLY;
                break;
            };

            m_pending.remove(pendingKey);
            Integer publishedKey = new Integer(info.trackId);
            m_published.put(publishedKey, info);

            publishedCount++;

            // Move to the next key in the pending map, or drop out
            // the loop if the map is now empty.
            if (m_pending.size() == 0) {
                return;
            } else {
                pendingKey = m_pending.firstKey();
            }
        }   
    }
    
    public static TrackState[] getTrackStates () {
        updateObjects ();
        TrackState[] tss = new TrackState[m_published.size()];
        int index = 0;
        synchronized (m_published) {
            Set<Integer> keys = m_published.keySet();
            Iterator<Integer> keysIter = keys.iterator();
            while (keysIter.hasNext()) {
                Integer key = (Integer) keysIter.next();
                TrackState tracked = (TrackState) m_published.get(key);
                tss[index] = tracked;
                index++;
            }
        }
        return tss;
    }
}
